package org.ala.tiktools.pacemaker;


import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;

import org.ala.tiktools.logs.*;
import org.ala.tiktools.pacemaker.wakeups.WakeupResult;
import org.slf4j.Logger;

/**
 * 默认实现
 * -    提供公共的线程池，用于执行唤醒任务
 *
 * @author ala
 * @date 2024-12-18 15:27
 */
public abstract class AbstractPacemaker implements IPacemaker {


    static Logger log = LoggerFactory.getLogger("tiktools", "pacemaker");


    /**
     *  执行任务线程池相关参数
     */
    protected int coreSize = 1, maxSize = 5, queueSize = 1024;

    /**
     *  执行任务的线程池
     */
    protected ThreadPoolExecutor threadPool;
    /**
     *  初始化
     */
    protected ThreadPoolExecutor threadPool() {
        if (threadPool == null) {
            synchronized (this) {
                if (threadPool == null) {
                    AtomicInteger cnt = new AtomicInteger();
                    threadPool = new ThreadPoolExecutor(coreSize, maxSize, 180, TimeUnit.SECONDS,
                            new ArrayBlockingQueue<>(queueSize),
                            new ThreadFactory() {
                                @Override
                                public Thread newThread(Runnable r) {
                                    Thread t = new Thread(r);
                                    t.setName(String.format("PacemakerThread_%d", cnt.getAndIncrement()));
                                    t.setDaemon(false);
                                    return t;
                                }
                            });
                }
            }
        }
        return threadPool;
    }


    @Override
    public void appendWakeup(long interval, IWakeuper wakeuper, IReject reject) {
        this.appendWakeup(interval, wakeuper, null, reject);
    }

    @Override
    public void appendWakeup(long interval, IWakeuper wakeuper, IWakeupError error) {
        this.appendWakeup(interval, wakeuper, error, null);
    }

    @Override
    public void appendWakeup(long interval, IWakeuper wakeuper) {
        this.appendWakeup(interval, wakeuper, null, null);
    }

    /**
     *  执行任务
     */
    protected void doWakeup(IWakeuper wakeuper, IWakeupError error, IReject reject, Consumer<WakeupResult> consumer, Runnable complate) {
        try {
            threadPool().execute(() -> {
                try {
                    WakeupResult res = wakeuper.doWakeup();
                    consumer.accept(res);
                } catch (Exception e) {
                    log.error("[AbstractPacemaker doWakeup] 执行唤醒任务出错", e);
                    if (error != null) {
                        error.onException(wakeuper, e);
                    }
                } finally {
                    if (complate != null) {
                        complate.run();
                    }
                }
            });
        } catch (Exception e) {
            log.error("[AbstractPacemaker doWakeup] 执行唤醒任务被拒绝", e);
            if (reject != null) {
                reject.onReject(wakeuper, e);
            }
            if (complate != null) {
                complate.run();
            }
        }
    }

}
